﻿using System;
using System.Collections.Generic;
using System.Net;
using System.Windows;
using Microsoft.Phone.Controls;
using System.Windows.Media.Imaging;
using System.IO;
using System.Device.Location;
using System.Threading;
using System.Xml.Linq;

namespace geopg_wp7
{
    public partial class LocalPicturesPage : PhoneApplicationPage
    {
        public Dictionary<string, object> parameters;
        public List<Picture> Pictures = new List<Picture>();
        string boundary = "----------" + DateTime.Now.Ticks.ToString();
        public Double gpsLong;
        public Double gpsLat;
        GeoCoordinateWatcher watcher;

        public LocalPicturesPage()
        {
            InitializeComponent();
        }

        public struct Picture
        {
            public int id;
            public int uploaderid;
            public string name;
            public string url;
            public double latitude;
            public double longitude;
            public int rating;
            public int views;
            public int dateupload;
        }

        protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e)
        {
            base.OnNavigatedTo(e);            
            PictureRequest();
        }

        private void getGPS()
        {
            // The watcher variable was previously declared as type GeoCoordinateWatcher. 
            if (watcher == null)
            {
                watcher = new GeoCoordinateWatcher(GeoPositionAccuracy.High); // using high accuracy
                watcher.MovementThreshold = 20; // use MovementThreshold to ignore noise in the signal
                watcher.StatusChanged += new EventHandler<GeoPositionStatusChangedEventArgs>(watcher_StatusChanged);
                watcher.PositionChanged += new EventHandler<GeoPositionChangedEventArgs<GeoCoordinate>>(watcher_PositionChanged);
                watcher.Start();
            }
        }

        // Event handler for the GeoCoordinateWatcher.StatusChanged event.
        void watcher_StatusChanged(object sender, GeoPositionStatusChangedEventArgs e)
        {
            switch (e.Status)
            {
                case GeoPositionStatus.Disabled:
                    // The Location Service is disabled or unsupported.
                    // Check to see whether the user has disabled the Location Service.
                    if (watcher.Permission == GeoPositionPermission.Denied)
                    {
                        // The user has disabled the Location Service on their device.
                        MessageBox.Show("you have this application access to location.");
                    }
                    else
                    {
                        MessageBox.Show("location is not functioning on this device"); 
                    }
                    break;

                case GeoPositionStatus.Initializing:
                    // The Location Service is initializing.     
                    break;

                case GeoPositionStatus.NoData:
                    // The Location Service is working, but it cannot get location data.                    
                    MessageBox.Show("location data is not available.");                    
                    break;

                case GeoPositionStatus.Ready:
                    // The Location Service is working and is receiving location data.                    
                    MessageBox.Show("location data is available.");                    
                    break;
            }
        }

        void watcher_PositionChanged(object sender, GeoPositionChangedEventArgs<GeoCoordinate> e)
        {
            gpsLat = e.Position.Location.Latitude;
            gpsLong = e.Position.Location.Longitude;
        }

        private void PictureRequest()
        {
            try
            {
                getGPS();
            }
            catch (ArgumentNullException) { /* Nothing */ }
            parameters = new Dictionary<string, object>()
            {
                {"lattitude", gpsLat},
                {"longitude", gpsLong},
                {"radius", 20},
                {"limit", 5},
            };
            // Prepare web request...
            Uri address = new Uri("http://geopg.de/backend/PictureList");
            HttpWebRequest myRequest = WebRequest.Create(address) as HttpWebRequest;
            myRequest.Method = "POST";
            myRequest.ContentType = string.Format("multipart/form-data; boundary={0}", boundary);
            myRequest.BeginGetRequestStream(new AsyncCallback(GetRequestStreamCallback), myRequest);
        }

        private void GetRequestStreamCallback(IAsyncResult asynchronousResult)
        {
            this.Dispatcher.BeginInvoke(delegate()
            {                              
                HttpWebRequest request = (HttpWebRequest)asynchronousResult.AsyncState;
                Stream postStream = request.EndGetRequestStream(asynchronousResult);
                writeMultipartObject(postStream, parameters);
                postStream.Close();
                request.BeginGetResponse(new AsyncCallback(GetResponseCallback), request);
            });
        }

        private void GetResponseCallback(IAsyncResult asynchronousResult)
        {
            try
            {
                HttpWebRequest request = (HttpWebRequest)asynchronousResult.AsyncState;
                HttpWebResponse response = (HttpWebResponse)request.EndGetResponse(asynchronousResult);
                Stream streamResponse = response.GetResponseStream();
                StreamReader streamRead = new StreamReader(streamResponse);
                string responseString = streamRead.ReadToEnd();
                this.Dispatcher.BeginInvoke(delegate()
                {                    
                    // Output is the position of the string. If it doesn't exist, its position is "-1"
                    if (responseString.IndexOf("cause") != -1)
                    {
                        if (responseString.IndexOf("cause=\"0\"") != -1)
                            MessageBox.Show("Internal Error (SQL)");
                        else if (responseString.IndexOf("cause=\"1\"") != -1)
                            MessageBox.Show("the HTTP method used is not supported.");
                        else if (responseString.IndexOf("cause=\"25\"") != -1)
                            MessageBox.Show("a parameter limit does not meet the required criteria.");
                        else if (responseString.IndexOf("cause=\"26\"") != -1)
                            MessageBox.Show("the request yielded an empty result (maybe criteria too restrictive).");
                        else if (responseString.IndexOf("cause=\"27\"") != -1)
                            MessageBox.Show("the parameter radius does not meet the required criteria (too big big?).");
                        else if (responseString.IndexOf("cause=\"28\"") != -1)
                            MessageBox.Show("a parameter (latitude or longitude) does not meet the required criteria.");                        
                        else
                            MessageBox.Show("An unexpected error occured.");
                    }
                    else
                    {
                        //<result value="OK">
                        //<picture id="42" uploaderid="3" name="Example Picture" url="http://example.com/" latitude="5.1234" longitude="5.1234" rating="2" views="42" dateupload="1234567890" />
                        //<picture id="23" uploaderid="5" name="Picture Example" url="http://example.org/" latitude="5.4321" longitude="5.4321" rating="4" views="23" dateupload="2345678901" />
                        //</result>

                        String [] results = responseString.Substring(20).Split('>');
                        
                        var result = XDocument.Parse(responseString);

                        Picture tempPic = new Picture(); 

                        while (result.Element("id") != null)
                        {                            
                            tempPic.id = (int)result.Element("id");
                            result.Element("id").ReplaceWith("read");

                            tempPic.uploaderid = (int)result.Element("uploaderid");
                            result.Element("uploaderid").ReplaceWith("read");

                            tempPic.name = (string)result.Element("name");
                            result.Element("name").ReplaceWith("read");

                            tempPic.url = (string)result.Element("url");
                            result.Element("url").ReplaceWith("read");

                            tempPic.latitude = (double)result.Element("latitude");
                            result.Element("latitude").ReplaceWith("read");

                            tempPic.longitude = (double)result.Element("longitude");
                            result.Element("longitude").ReplaceWith("read");

                            tempPic.rating = (int)result.Element("rating");
                            result.Element("rating").ReplaceWith("read");

                            tempPic.views = (int)result.Element("views");
                            result.Element("views").ReplaceWith("read");

                            tempPic.dateupload = (int)result.Element("dateupload");
                            result.Element("dateupload").ReplaceWith("read");                            
                        }
                        Pictures.Add(tempPic);
                        
                        MessageBox.Show("successfully loaded pictures" + responseString);
                    }

                });
                streamResponse.Close();
                streamRead.Close();
                // Release the HttpWebResponse
                response.Close();
            }
            catch (WebException e)
            {
                this.Dispatcher.BeginInvoke(delegate()
                {
                    MessageBox.Show("Can't establish connection.");
                });
            }
        }


        public void writeMultipartObject(Stream stream, object data)
        {
            StreamWriter writer = new StreamWriter(stream);
            if (data != null)
            {
                foreach (var entry in data as Dictionary<string, object>)
                {
                    WriteEntry(writer, entry.Key, entry.Value);
                }
            }
            writer.Write("--");
            writer.Write(boundary);
            writer.WriteLine("--");
            writer.Flush();
        }

        private void WriteEntry(StreamWriter writer, string key, object value)
        {
            if (value != null)
            {
                writer.Write("--");
                writer.WriteLine(boundary);
                writer.WriteLine(@"Content-Disposition: form-data; name=""{0}""", key);
                writer.WriteLine();
                writer.WriteLine(value.ToString());
            }
        }

        private void searchLocationButton_Click(object sender, EventArgs e)
        {
            //
            // Check if GPS is enabled (GPS seems to be enabled)
            //
            GeoCoordinateWatcher g = new GeoCoordinateWatcher();
            if (GeoPositionStatus.Disabled == g.Status)
                MessageBox.Show("You must enable Location Services to use this Feature.");
            if (GeoPositionStatus.Disabled != g.Status)
                NavigationService.Navigate(new Uri("//LocationSearchPage.xaml", UriKind.Relative));
        }

        private void login_Click(object sender, EventArgs e)
        {
            NavigationService.Navigate(new Uri("//LoginPage.xaml", UriKind.Relative));
        }

        private void mainPage_Click(object sender, EventArgs e)
        {
            NavigationService.Navigate(new Uri("//MainPage.xaml", UriKind.Relative));
        }

        private void localPictures_Click(object sender, EventArgs e)
        {
            NavigationService.Navigate(new Uri("//LocalPicturesPage.xaml", UriKind.Relative));
        }

        private void settings_Click(object sender, EventArgs e)
        {
            NavigationService.Navigate(new Uri("//SettingsPage.xaml", UriKind.Relative));
        }

        private void info_Click(object sender, EventArgs e)
        {
            NavigationService.Navigate(new Uri("//InfoPage.xaml", UriKind.Relative));
        }



        private void bigImage_ImageFailed(object sender, EventArgs e)
        {
            
        }

    }
}